'''###########################################################################################################################
### File: game_loader.py
### Name: Patrick Delaney, Andrew Oberlin
### Class: CSE 487
### Instructor: Dr.Zmuda
### Assignment: Final Project
### Description: Loads a game made by the level editor
################ 
'''
from menu_button import MenuButton
from panda3d.core import Vec2, Point3, Vec3, Vec4, BitMask32
from Tkinter import Tk
from tkFileDialog import askopenfilename
from panda3d.core import Filename
from direct.gui.DirectGui import *
from level import Level
from pandac.PandaModules import CollisionSphere, CollisionNode, CollisionTraverser, CollisionHandlerQueue
from pandac.PandaModules import TextureStage
import math
import os
import string
from animation import Animation

class GameLoader:
	SPEED = 2
	JUMP_SPEED = 4
	JUMP_HEIGHT = 0.5
	'''
	### Name: __init__ (Constructor)
	### Author: Andrew Oberlin, Patrick Delaney
	### Parameters: None
	### Description: Initializes all the game maker gui, which
					 requires a project name to move on
	'''
	def __init__(self, parent, mainGui):
		self.parent = parent
		self.mainGui = mainGui
		self.mainCharacter = None
		self.models = dict()
		self.levelObjects = None
		self.__loadModels()
		
	'''
	### Name: loadModels
	### Author: Andrew Oberlin, Patrick Delaney
	### Parameters: None
	### Description: Loads the GUI objects
	'''
	def __loadModels(self):
		self.models['background'] = self.parent.loader.loadModelCopy("models/plane")
		self.backgroundTexture = self.parent.loader.loadTexture("models/gui/game_maker/menu_background.jpg")
		self.models['background'].setTexture(self.backgroundTexture)
		self.models['background'].setTransparency(1)
		self.models['background'].setScale(2.67, 1, 2)
		self.models['background'].reparentTo(self.parent.base.aspect2d)
		
		self.models['logo'] = self.parent.loader.loadModelCopy("models/plane")
		self.logoTexture = self.parent.loader.loadTexture("models/gui/game_maker/game_maker_logo.png")
		self.models['logo'].setTexture(self.logoTexture)
		self.models['logo'].setTransparency(1)
		self.models['logo'].setScale(2.67, 1, 0.35)
		self.models['logo'].setPos(0, 0, 0.75)
		self.models['logo'].reparentTo(self.parent.base.aspect2d)
		
		self.models['back_button'] = MenuButton(self.parent, 'create_object_button', 'models/gui/game_maker/back_button', 
			self.goBack, Vec3(-.90, 0, -.80),scale=0.25, textPos=Vec3(-0.20, 0, .15), isMovie = False, text="Go Back")
		
		self.models['load_button'] = MenuButton(
			self.parent, 'load_button', 'models/gui/game_maker/dialog_button', 
			self.loadLevel, Vec3(0, 0, 0), isMovie = False, text="Load Existing Level", 
			textPos=Vec3(-0.45, 0, -0.025), scale=Vec3(1.1,1,0.3)
		)
	'''
	### Name: hide
	### Author: Andrew Oberlin, Patrick Delaney
	### Parameters: None
	### Description: hides this GUI
	'''
	def hide(self):
		for key in self.models.keys():
			self.models[key].hide()
	
	'''
	### Name: show
	### Author: Andrew Oberlin, Patrick Delaney
	### Parameters: None
	### Description: show this GUI
	'''
	def show(self):
		for key in self.models.keys():
			self.models[key].show()
	
	'''
	### Name: goBack
	### Author: Andrew Oberlin, Patrick Delaney
	### Parameters: None
	### Description: goes back to the previous GUI
	'''
	def goBack(self):
		self.hide()
		self.mainGui.show()
	'''
	### Name: loadLevel
	### Author: Andrew Oberlin, Patrick Delaney
	### Parameters: None
	### Description: loads the level
	'''
	def loadLevel(self):
		try:
			root=Tk()
			self.file_opt = options = {}
			options['defaultextension'] = '' # couldn't figure out how this works
			options['filetypes'] = [('Level Files', '.lvl')]
			options['parent'] = root
			options['title'] = 'Load a Level!'
			self.levelFile = askopenfilename(**self.file_opt)
			
			root.destroy()
			self.hide()
			self.level = Level()
			self.level.load(self.levelFile)
			self.jumping = False
			
			self.levelObjects = dict()
			# need to find the boundaries of the level for the camera
			mostLeft = 1000000000
			mostRight = -1000000000
			for key in self.level.objects.keys():
				self.levelObjects[key] = self.level.objects[key].exportToVisualObject(self.parent, self.parent.render)
				if (self.levelObjects[key].getX() < mostLeft):
					mostLeft = self.levelObjects[key].getX()
				
				if (self.levelObjects[key].getX() > mostRight):
					mostRight = self.levelObjects[key].getX()
					
			self.mainCharacter = self.level.mainCharacter.exportToVisualObject(self.parent, self.parent.render)
			
			directoryArr = Filename(self.levelFile).getDirname().split("/")
			directoryArr.pop()
			upDir = "/".join(directoryArr)
			animDir = upDir + "/characters/main/" + self.mainCharacter.object.name
			self.walkAnimation = None
			for item in os.listdir(animDir):
				if(string.find(item, "Walk.anim") > -1):
					self.walkAnimation = Animation()
					self.walkAnimation.load(animDir + "/Walk.anim")
					break
					
			if (self.walkAnimation):
				self.walkAnimationMovie = self.walkAnimation.exportAsTexturesList(self.parent)
			self.setupCollisions()
			
			self.parent.accept("a", self.startWalk, [-1])
			self.parent.accept("d", self.startWalk, [1])
			self.parent.accept("a-up", self.stopWalk, [-1])
			self.parent.accept("d-up", self.stopWalk, [1])
			self.parent.accept("w", self.startJump)
		
			self.velocity = Vec2(0,0)
			self.walkingTask = self.parent.taskMgr.add(self.gameLoop, "gameLoop")
			self.walkingTask.fps = 10
			self.walkingTask.prevTime = 0
			
			self.parent.cameraController.moveTo(x=0)
			
			
			
		except IOError, e:
			print "Problem loading level!"
			
	
	'''
	
	'''
	def startJump(self):
		self.velocity[1] = self.JUMP_SPEED
		self.originalJumpZ = self.mainCharacter.getZ()
		self.jumping = True
		self.parent.ignore("w")
	
	def startWalk(self, direction):
		scale = self.mainCharacter.model.getTexScale(TextureStage.getDefault())
		self.mainCharacter.model.setTexScale(TextureStage.getDefault(), math.fabs(scale[0])*direction, scale[1])
		self.velocity[0] = direction*self.SPEED
	
	def stopWalk(self, direction):
		if ((self.velocity[0] > 0) == (direction > 0)):
			self.velocity[0] = 0
	
	'''
		
	'''
	def gameLoop(self,task):
		deltaT = task.time - task.prevTime
		task.prevTime = task.time
		currentFrame = int(task.time * task.fps)
	
		self.mainCharacter.setPos(self.mainCharacter.getPos() + Vec3(self.velocity[0]*deltaT, 0, self.velocity[1]*deltaT))
		
		if (self.walkAnimation and self.velocity[0] != 0 and self.velocity[1] == 0):
			self.mainCharacter.setModelTexture(self.walkAnimationMovie[currentFrame % len(self.walkAnimation.getTextures())])
		else:
			self.mainCharacter.setObjectType(self.mainCharacter.object)
		
		if (self.velocity[1] > 0 and self.jumping):
			if (self.mainCharacter.getZ() >= self.JUMP_HEIGHT):
				self.velocity[1] = self.JUMP_SPEED * -1
				self.jumping = False
				
		return task.cont
		
	def setupCollisions(self):
		#use an event collision handler( sends events on collisions)
		self.collQueue = CollisionHandlerQueue()
		
		#Add collision Patterns here
		#Self.cHandler.addInPattern("name-%in")  - in will be the name of the object
		
		# make a traverser and make it the default traverser
		self.parent.base.cTrav = CollisionTraverser()
		self.traverser = self.parent.base.cTrav
		
		for key in self.levelObjects.keys():
			if (self.levelObjects[key].object.getIsPlatform()):
				self.levelObjects[key].model.setCollideMask(BitMask32(0x10))
				
		self.traverser.addCollider(self.mainCharacter.cnodePath, self.collQueue)
		
		#To add colliders cTrav.addCollider(CollisionNode, self.cHandler)
		#Then self.cNodePaths.append
		floorTask = self.parent.taskMgr.add(self.floorTask, "floor_task")
		floorTask.prevTime = 0
		
	
	
	
		
	'''
		Makes this character follow the
		enemy to attack them
	'''
	def floorTask(self, task):
		deltaT = task.time - task.prevTime
		task.prevTime = task.time
		
		self.traverser.traverse(self.parent.render)
		self.collQueue.sortEntries()
		for i in range(self.collQueue.getNumEntries()):
			cEntry = self.collQueue.getEntry(i)
			geom = cEntry.getIntoNodePath()
			
			tag = geom.getTag('key')
			while geom and tag == "":
				tag = geom.getParent().getTag('key')
				geom = geom.getParent()
				
			if (self.levelObjects.has_key(tag)):
				obj = self.levelObjects[tag]
				if (obj.object.getIsPlatform()):
					# collided with a platform
					if (self.velocity[1] < 0):
						self.velocity[1] = 0
						self.parent.accept("w", self.startJump)
					
		return task.cont